package com.hxut.filter;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.hxut.common.exception.CaptchaException;
import com.hxut.common.lang.Const;
import com.hxut.security.LoginFailureHandler;
import com.hxut.utils.RedisUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;


/**
 * description: CaptchaFilter
 * date: 2022/7/6 13:29
 * author: MR.孙
 */

//OncePerRequestFilter是在一次外部请求中只过滤一次。对于服务器内部之间的forward等请求，不会再次执行过滤方法。
@Component
public class CaptchaFilter extends OncePerRequestFilter {

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private LoginFailureHandler loginFailureHandler;


    @Override
    protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
        //获取请求url
        String url = httpServletRequest.getRequestURI();

        //拦截login登录路径
        if ("/login".equals(url) && httpServletRequest.getMethod().equals("POST")) {
            try {
                // 校验验证码
                validate(httpServletRequest);
            } catch (CaptchaException e) {
                // 交给认证失败处理器
                loginFailureHandler.onAuthenticationFailure(httpServletRequest,httpServletResponse,e);
            }

        }
        //放行
        filterChain.doFilter(httpServletRequest,httpServletResponse);

    }

    /**
     * @description:  校验验证码
     * @param request
     * @return: void
     * @author: MR.孙
     * @date: 2022/7/6 13:44
     */
    private void validate(HttpServletRequest request) {
        String code = request.getParameter("code");
        String key = request.getParameter("token");

        //对code和key进行判断，如果是空的话，就不用校验了
        //如果给定的字符串为空或仅包含空格代码点，则此方法返回 true ，否则返回 false
        if (StringUtils.isBlank(code) || StringUtils.isBlank(key)) {
            throw new CaptchaException("验证码错误");
        }
        //如果页面传递的验证码和redis中的验证码也不一致
        if (!code.equals(redisUtils.hget(Const.Captcha, key))) {
            throw new CaptchaException("验证码错误");
        }


        //验证码一次使用
        redisUtils.hdel(Const.Captcha, key);
    }
}

